package ofertas;

import static org.junit.Assert.*;
import static org.mockito.Mockito.*;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.junit.Before;
import org.junit.Test;

import productosYPresentaciones.Producto;

/**
 * Test de la clase de oferta que esta constituida por otras ofertas.
 * @author Octavio.
 */

public class OfertaCompuestaTest extends OfertaTest{

	private Producto producto4;
	
	@Override
	@Before
	public void setUp() throws Exception {
		super.setUp();
		producto4 = mock( Producto.class );
		List<Oferta> ofertas = new ArrayList<Oferta>();
		//Precausion: El orden en el que se entrega la lista de ofertas
		//influye en el resultado de .getListaProductos() (orden)
		ofertas.add( new OfertaProductos(porc,lfake) );
		ofertas.add( new OfertaUnSoloProducto(porc,producto4) );
		
		oferta = new OfertaCompuesta(porc, ofertas);
	}
	
	@Test
	public void testPrecioOferta() {
		float suma = (producto1.precioActual() + producto2.precioActual())*(1-porc)
				 + producto4.precioActual()*(1-porc);
		assertEquals( suma*(1-porc), oferta.precioOferta(), 0.02 );
	}

	@Test
	public void testGetListaProductos() {
		//No son iguales porque falta un producto
		List<Producto> lista = oferta.getListaProductos();
		assertEquals( 3, lista.size());
		assertNotSame( lfake.toArray(), lista.toArray() );
		//lo agrego
		lfake.add(producto4);
		assertArrayEquals( lfake.toArray(), lista.toArray());
	}

	@Test
	public void testGetProductos() {
		Map<Producto,Integer> mapa = oferta.getProductos();
		assertEquals( 3, mapa.size() );
		assertTrue( mapa.containsKey(producto1) );
		assertTrue( mapa.containsKey(producto2) );
		assertTrue( mapa.containsKey(producto4) );
		assertEquals( 1, mapa.get(producto1).intValue() );
		assertEquals( 1, mapa.get(producto2).intValue() );
		assertEquals( 1, mapa.get(producto4).intValue() );
	}

	
	@Test
	public void testHayOfertasConProductos() {
		//Creo un map, que esencialmente tiene el mismo contenido
		//que la lista lfake: producto1-2
		Map<Producto,Integer> mfake = mock( Map.class );
		
		//Declaro las condiciones iniciales
		when(mfake.containsKey(producto1)).thenReturn(true);
		when(mfake.get(producto1)).thenReturn(1);
		when(mfake.containsKey(producto2)).thenReturn(true);
		when(mfake.get(producto2)).thenReturn(1);
		
		when(mfake.containsKey(producto4)).thenReturn(false);
		//Compruebo que se aplica la oferta
		assertFalse( oferta.puedeAplicarOferta(mfake) );
		//Y que tampoco necesita saber el estado de productos desconocidos
		verify(mfake,times(0)).containsKey(producto3);
		
		//Agrego el producto4
		when(mfake.containsKey(producto4)).thenReturn(true);
		when(mfake.get(producto4)).thenReturn(1);
		assertTrue( oferta.puedeAplicarOferta(mfake) );
	}
}
